﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace CoreLims.Models.CoreLims
{
    using Analyte = SampleAnalyte;
    using LoginRelation = SampleLoginRelation;
    using Method = SampleMethod;
    using Relation = SampleRelation;
    using Result = SampleResult;
    using Sample = SampleSample;
    using SampleBatch = SampleSampleBatch;
    using SampleDefinition = SampleSampleDefinition;
    using SampleGroup = SampleSampleGroup;
    using Spec = SampleSpec;
    using TestDefinition = SampleTestDefinition;
    using TestRelation = SampleTestRelation;

    public sealed partial class SAMPLE
    {
        public static Analyte Analyte;
        public static Relation Relation;
        public static Result Result;
        public static Sample Sample;
        public static SampleBatch SampleBatch;
        public static LoginRelation LoginRelation;
        public static SampleDefinition SampleDefinition;
        public static Spec Spec;
        public static TestRelation TestRelation;
        public static TestDefinition TestDefinition;
        public static SampleGroup SampleGroup;
        public static Method Method;
        public static RetentionSample RetentionSample;
        public static RetentionConfig RetentionConfig;
        public static RetentionUse RetentionUse;

        public static Func<string> _newId = () => Guid.NewGuid().ToString();

        /// <summary>
        /// 样品状态
        /// </summary>
        public enum SampleStatus { 登录, 检测中, 完成, 废弃 };

        /// <summary>
        /// 结果录入模式
        /// </summary>
        public enum EntryModel { 手工, 仪器, 计算 };

        /// <summary>
        /// 结果状态, OOG 的意思为超过二倍限，但没超过三倍限。
        /// </summary>
        public enum ResultStatus { Done, OOG ,OOS };

        /// <summary>
        /// 更新分析项默认指标
        /// </summary>
        /// <param name="SpecID"></param>
        /// <param name="AnalyteID"></param>
        public static void UpdateRelationSpecAndAanylte(CoreLimsContext dbContext, string SpecID, string AnalyteID)
        {
            var analyte = dbContext.Analyte.FirstOrDefault(s => s.Id == AnalyteID);
            var spec = dbContext.Spec.FirstOrDefault(s => s.Id == SpecID);

            analyte.DefaultSpecId = SpecID;
            analyte.DefaultSpecName = spec.Name;

            dbContext.Update(analyte);
            dbContext.SaveChanges();
        }

        /// <summary>
        /// 删除分析项默认指标
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="AnalyteID"></param>
        public static void DelteRelationSpecAndAanylte(CoreLimsContext dbContext, string AnalyteID)
        {
            var analyte = dbContext.Analyte.Where(s => s.Id == AnalyteID).FirstOrDefault();

            analyte.DefaultSpecId = null;
            analyte.DefaultSpecName = null;

            dbContext.Update(analyte);
            dbContext.SaveChanges();
        }

        /// <summary>
        /// 根据 WorkFlowId 和 可跳过步骤设置，返回步骤设置列表
        /// </summary>
        /// <param name="WorkFlowId"></param>
        /// <param name="SkipSequence"></param>
        /// <returns></returns>
        public static List<SkipSequence> GetWorkflowStepSequence(string WorkFlowId, string SkipSequence)
        {
            var wf = WorkFlow.GetWorkFlow(WorkFlowId);
            var list = wf.GetOrderStepSequenceList();

            if (list == null || list.Count == 0)
                return null;

            var useList = SkipSequence;
            var utl = new List<SkipSequence>();

            for (int i = 1; i < list.Count - 1; i++)
            {
                utl.Add(new SkipSequence
                { Id = list[i].Id, Skip = string.IsNullOrEmpty(useList) ? false : useList.Contains(list[i].Id), StepName = list[i].StepName });
            }

            return utl;
        }

        public static void RunWorkflow(CoreLimsContext dbContext, Sample sp, string userID, string userName)
        {
            var workFlow = WorkFlow.GetRuntimeWorkFlow(sp);
            workFlow.SkipRunWorkFlow(sp.SkipSequence, userName, userID); // 原来定义的 type 用来存放用户名。

            var name = workFlow.getCurrentRunStepName();
            var nextName = workFlow.getCurrentNextRunStepName();
            sp.CurrentWorkFlow = name;
            sp.NextWorkFlow = nextName;
            if (name == null)
            {
                sp.Status = SampleStatus.完成.ToString();
                sp.CompleteTime = DateTime.Now;

                if (sp.IsRetention)
                {
                    var newRetention = new RetentionSample();
                    newRetention.CopySample(sp, dbContext);
                    dbContext.Add(newRetention);
                }
            }
            dbContext.Update(sp);
        }

        /// <summary>
        /// 重测，退回到结果录入步骤
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="sp"></param>
        public static void TakeAStepBack(CoreLimsContext dbContext, Sample sp)
        {
            var workFlow = WorkFlow.GetRuntimeWorkFlow(sp);
            var currentname = workFlow.getCurrentRunStepName();
            if (currentname != "结果录入") // 审核时可能会有多个项目需要重测，如果当前已经被退回，则不需要再次操作
            {
                var currentID = workFlow.getCurrentRunStepID();
                var backStep = workFlow.getRunStepByStepname("结果录入");

                workFlow.TakeAStepBack(currentID, backStep.Id, null, null); // 需要用户

                var name = workFlow.getCurrentRunStepName(); // 流程退回后，需要修改Sample表中指示流程位置的字段
                var nextName = workFlow.getCurrentNextRunStepName();
                sp.CurrentWorkFlow = name;
                sp.NextWorkFlow = nextName;
                dbContext.Update(sp);
            }
        }

        /// <summary>
        /// 废弃样品时，结束该样品流程。
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="sp"></param>
        public static void DoEndStep(CoreLimsContext dbContext, Sample sp, CommonUser user, string Suggestion)
        {
            var workFlow = WorkFlow.GetRuntimeWorkFlow(sp);
            workFlow.ToEndStep(Suggestion);

            sp.Status = SampleStatus.废弃.ToString();
            sp.CompleteTime = DateTime.Now;
            sp.CurrentWorkFlow = null;
            sp.NextWorkFlow = null;

            dbContext.Update(sp);
            dbContext.SaveChanges();
        }
    }

    /// <summary>
    /// 分析项定义
    /// </summary>
    public partial class SampleAnalyte
    {
        public string Id { get; set; }

        /// <summary>
        /// 代码，比如 Au,Ag 导入数据时，根据代码来识别对应的分析项
        /// </summary>
        public string Code { get; set; }

        /// <summary>
        /// 英文名称
        /// </summary>
        public string English { get; set; }

        /// <summary>
        /// 中文名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 分类
        /// </summary>
        public string Classification { get; set; }

        /// <summary>
        /// 结果模式 string/int/decimal
        /// </summary>
        public string ResultModel { get; set; }

        /// <summary>
        /// 修约 同时指定修约模式和保留小数位数。ISO,1  FDA,2(四舍六入保留两位) ENOB,3 有效数字。
        /// 如果结果模式是 string/int ，则该项不需要设置。
        /// </summary>
        public string RoundingOff { get; set; }

        /// <summary>
        /// 原始结果单位
        /// </summary>
        public string Units { get; set; }

        /// <summary>
        /// 最终结果单位
        /// </summary>
        public string FUnits { get; set; }

        /// <summary>
        /// 默认指标
        /// </summary>
        public string DefaultSpecId { get; set; }

        /// <summary>
        /// 默认指标名
        /// </summary>
        public string DefaultSpecName { get; set; }

        /// <summary>
        /// 单位类型
        /// </summary>
        public string UnitsType { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 报告过滤：辅助项指示，如果为 true ，则在出报告的时候过滤掉该项
        /// </summary>
        public bool Assist { get; set; }

        /// <summary>
        /// 设备类型，绑定设备类型的分析项在手工录入结果时可选择具体设备
        /// </summary>
        public string EqType { get; set; }

        /// <summary>
        /// 检出限 如果定义该值，则最终结果小于等于该值时，最终结果将变为小于号加该值的形式
        /// </summary>
        public string DetectionLimit { get; set; }

        /// <summary>
        /// 默认值
        /// </summary>
        public string DefaultValue { get; set; }

        /// <summary>
        /// 备选结果 该值为“,”分隔的字符串，用来提供可能的结果
        /// </summary>
        public string AlternativeResults { get; set; }

        /// <summary>
        /// 关联的方法ID 如果该分析项被加入到测试中，则测试中绑定的方法将替换该值存入结果表。
        /// </summary>
        public string MethodId { get; set; }

        /// <summary>
        /// 关联的方法代码
        /// </summary>
        public string MethodCode { get; set; }

        /// <summary>
        /// 是否过 CMA 认证
        /// </summary>
        public bool CMA { get; set; }

        /// <summary>
        /// 是否过 CNAS 认证
        /// </summary>
        public bool CNAS { get; set; }
    }

    /// <summary>
    /// 包含关系映射表
    /// </summary>
    public partial class SampleRelation
    {
        public SampleRelation()
        {
            Id = SAMPLE._newId();
        }
        public string Id { get; set; }

        /// <summary>
        /// 源表名
        /// </summary>
        public string SourceTabName { get; set; }

        /// <summary>
        /// 源记录ID
        /// </summary>
        public string SourceId { get; set; }

        /// <summary>
        /// 被包含表名
        /// </summary>
        public string IncludedTabName { get; set; }

        /// <summary>
        /// 被包含记录ID
        /// </summary>
        public string IncludedId { get; set; }

        /// <summary>
        /// 样品包含的分析项和测试的检测次数。
        /// 如果该条记录是样品包含的指标集记录，Repeat=1 表示该指标集是默认指标集
        /// </summary>
        public int? Repeat { get; set; }

        public void Copy(SampleRelation other)
        {
            this.SourceTabName = other.SourceTabName;
            //this.SourceId = other.SourceId;
            this.IncludedId = other.IncludedId;
            this.IncludedTabName = other.IncludedTabName;
            this.Repeat = other.Repeat;
        }
    }

    /// <summary>
    /// 结果
    /// </summary>
    public partial class SampleResult
    {
        public SampleResult()
        {
            this.Id = SAMPLE._newId();
        }

        public string Id { get; set; }

        /// <summary>
        /// 样品ID
        /// </summary>
        public string SampleId { get; set; }

        /// <summary>
        /// 测试ID
        /// </summary>
        public string TestId { get; set; }

        /// <summary>
        /// 测试名称
        /// </summary>
        public string TestName { get; set; }

        /// <summary>
        /// 分析项ID
        /// </summary>
        public string AnalytesId { get; set; }

        /// <summary>
        /// 分析项代码，英文名
        /// </summary>
        public string AnalytesCode { get; set; }

        /// <summary>
        /// 分析项英文名称
        /// </summary>
        public string AnalytesEnglish {  get; set; }

        /// <summary>
        /// 分析项中文名称
        /// </summary>
        public string AnalytesName { get; set; }

        /// <summary>
        /// 原始结果
        /// </summary>
        public string Original { get; set; }

        /// <summary>
        /// 修约或计算后结果
        /// </summary>
        public string Final { get; set; }

        /// <summary>
        /// 状态 Done/OOS 结果检测不合格为OOS
        /// </summary>
        public string Status { get; set; }

        /// <summary>
        /// 是否强制通过该样品,暂未使用
        /// </summary>
        public bool? IsForce { get; set; }

        /// <summary>
        /// 结论，有些样品除了结果以外可能还需要结论 合格/不合格 等
        /// </summary>
        public string Conclusion { get; set; }

        /// <summary>
        /// 如果是强制通过的样品，该字段用来存放修约后结果，Final 则用来存放强行修改的结果。暂未使用
        /// </summary>
        public string OriginalFinal { get; set; }

        /// <summary>
        /// 结果模式 string/int/decimal
        /// </summary>
        public string ResultModel { get; set; }

        /// <summary>
        /// 修约 同时指定修约模式和保留小数位数。ISO,1  FDA,2(四舍六入保留两位)
        /// </summary>
        public string RoundingOff { get; set; }

        /// <summary>
        /// 原始结果单位
        /// </summary>
        public string Units { get; set; }

        /// <summary>
        /// 最终结果单位
        /// </summary>
        public string FUnits { get; set; }

        /// <summary>
        /// 三倍低限
        /// </summary>
        public string LowA { get; set; }

        /// <summary>
        /// 二倍低限
        /// </summary>
        public string LowB { get; set; }

        /// <summary>
        /// 标准值
        /// </summary>
        public string StandardValue { get; set; }

        /// <summary>
        /// 二倍高限
        /// </summary>
        public string HighB { get; set; }

        /// <summary>
        /// 三倍高限
        /// </summary>
        public string HighA { get; set; }

        /// <summary>
        /// 验收标准，出报告时放在报告上描述合格范围的文本信息
        /// </summary>
        public string AcceptanceCriteria { get; set; }

        /// <summary>
        /// 分析项或测试所引用的方法ID
        /// </summary>
        public string MethodId { get; set; }

        /// <summary>
        /// 关联的方法代码
        /// </summary>
        public string MethodCode { get; set; }

        /// <summary>
        /// 验收文本，针对文本型结果，该字段用来与输入结果进行比对，判断输入结果是否合格。暂未使用
        /// </summary>
        public string AcceptanceText { get; set; }

        /// <summary>
        /// 自定义计算规则，这个定义在指标或指标集上的计算规则的复制
        /// </summary>
        public string AcceptanceRules { get; set; }

        /// <summary>
        /// 自定义计算规则，这个定义是测试当中定义的规则的复制
        /// </summary>
        public string CalculationRules { get; set; }

        /// <summary>
        /// 结果录入模式(关联结构) 手工录入/仪器采集/计算
        /// </summary>
        public string EntryModel { get; set; }

        /// <summary>
        /// 关联的设备运行ID(设备使用记录ID)
        /// </summary>
        public string EqUsageRecordId { get; set; }

        /// <summary>
        /// 该项关联设备或导入数据结果的设备ID
        /// </summary>
        public string EqId { get; set; }

        /// <summary>
        /// 设备类型
        /// </summary>
        public string EqType { get; set; }

        /// <summary>
        /// 结果录入时间
        /// </summary>
        public DateTime? EntryTime { get; set; }

        /// <summary>
        /// 辅助项指示，如果为 true ，则在出报告的时候过滤掉该项
        /// </summary>
        public bool Assist { get; set; }

        /// <summary>
        /// 结果录入人ID
        /// </summary>
        public string EntryPersonId { get; set; }

        /// <summary>
        /// 结果录入人姓名
        /// </summary>
        public string EntryPersonName { get; set; }

        /// <summary>
        /// 重测次数，0代表非重测
        /// </summary>
        public int RetestNo { get; set; }

        /// <summary>
        /// 自定义排序，默认为0
        /// </summary>
        public int Sort { get; set; }

        /// <summary>
        /// 第几次检测，默认是1。该值与登录样品关系中的检测次数相关
        /// </summary>
        public int DetectionTimes { get; set; }

        /// <summary>
        /// 测试的重复次数，默认是1。对于不属于测试的分析项来说，该值无意义
        /// </summary>
        public int TestTimes { get; set; }

        /// <summary>
        /// 检出限  如果定义该值，则最终结果小于等于该值时，最终结果将变为“<DetectionLimit”的形式
        /// </summary>
        public string DetectionLimit { get; set; }

        /// <summary>
        /// 备选结果 该值为“,”分隔的字符串，用来提供可能的结果
        /// </summary>
        public string AlternativeResults { get; set; }

        /// <summary>
        /// 是否过 CMA 认证
        /// </summary>
        public bool CMA { get; set; }

        /// <summary>
        /// 是否过 CNAS 认证
        /// </summary>
        public bool CNAS { get; set; }

        /// <summary>
        /// 重测时复制必要信息，返回一条新纪录
        /// </summary>
        /// <returns></returns>
        public SampleResult Copy()
        {
            var result = new SampleResult();
            result.SampleId = this.SampleId;
            result.TestId = this.TestId;
            result.TestName = this.TestName;
            result.AnalytesId = this.AnalytesId;
            result.AnalytesCode = this.AnalytesCode;
            result.AnalytesName = this.AnalytesName;
            result.ResultModel = this.ResultModel;
            result.RoundingOff = this.RoundingOff;
            result.Units = this.Units;
            result.FUnits = this.FUnits;
            result.LowA = this.LowA;
            result.LowB = this.LowB;
            result.StandardValue = this.StandardValue;
            result.HighA = this.HighA;
            result.HighB = this.HighB;
            result.AcceptanceCriteria = this.AcceptanceCriteria;
            result.MethodId = this.MethodId;
            result.MethodCode = this.MethodCode;
            result.AcceptanceText = this.AcceptanceText;
            result.AcceptanceRules = this.AcceptanceRules;
            result.CalculationRules = this.CalculationRules;
            result.EqType = this.EqType;
            //result.EqUsageRecordId = this.EqUsageRecordId; 重测时有可能使用其它设备测试，所以此处不复制
            result.Assist = this.Assist;
            result.Sort = this.Sort;
            result.DetectionLimit = this.DetectionLimit;
            result.AlternativeResults = this.AlternativeResults;
            result.DetectionTimes = this.DetectionTimes; // 这个值对于属于测试的分析项来说具有意义，添加不属于测试的分析项时，需要改成1
            result.TestTimes = this.TestTimes; // 这个值在添加属于测试的的分析项时需要再修改
            result.CMA = this.CMA;
            result.CNAS = this.CNAS;
            return result;
        }
    }

    /// <summary>
    /// 登录样品
    /// </summary>
    public partial class SampleSample : IWorkFlow<SampleSample>
    {
        /// <summary>
        /// 样品ID,登录样品的唯一标识，用来与其它表关联
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// 样品ID,根据定义规则由系统自动生成的ID，由于存在重测的样品，所以该字段是允许重复的。
        /// </summary>
        public string SampleId { get; set; }

        /// <summary>
        /// 样品编号,客户附加到登录样品上的编号，也可以理解为内部编号或自定义编号，可为空
        /// </summary>
        public string SampleNumber { get; set; }

        /// <summary>
        /// 批次号，标识一个批次样品的编号，也可以理解为委托单号等。
        /// </summary>
        public string BatchId { get; set; }

        /// <summary>
        /// 样品名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 样品描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 样品类型 临时样/常规样/批次样/环境样/稳定性
        /// </summary>
        public string Classification { get; set; }

        /// <summary>
        /// 样品分类：原材料、中控样、半成品、成品等
        /// </summary>
        public string GenricClass { get; set; }

        /// <summary>
        /// 样品所属实验室
        /// </summary>
        public string Site { get; set; }

        /// <summary>
        /// 样品所属工作组
        /// </summary>
        public string Group { get; set; }

        /// <summary>
        /// 样品登录时间
        /// </summary>
        public DateTime LoginTime { get; set; }

        /// <summary>
        /// 登录人ID
        /// </summary>
        public string LoginPersonId { get; set; }

        /// <summary>
        /// 登录人姓名
        /// </summary>
        public string LoginPersonName { get; set; }

        /// <summary>
        /// 指派的分析人ID
        /// </summary>
        public string AssignPersonId { get; set; }

        /// <summary>
        /// 指派的分析人姓名
        /// </summary>
        public string AssignPersonName { get; set; }

        /// <summary>
        /// 指派的工作组ID
        /// </summary>
        public string AssignGroupId { get; set; }

        /// <summary>
        /// 指派的工作组名称
        /// </summary>
        public string AssignGroupName { get; set; }

        /// <summary>
        /// 关联的工作流ID
        /// </summary>
        public string WorkFlowId { get; set; }

        /// <summary>
        /// 当前所处工作流中的步骤
        /// </summary>
        public string CurrentWorkFlow { get; set; }

        /// <summary>
        /// 工作流中下一步骤
        /// </summary>
        public string NextWorkFlow { get; set; }

        /// <summary>
        /// 关联的采样ID
        /// </summary>
        public string SamplingPoint { get; set; }

        /// <summary>
        /// 关联的库存ID
        /// </summary>
        public string InventoryId { get; set; }

        /// <summary>
        /// 关联的物料ID
        /// </summary>
        public string MaterialId { get; set; }

        /// <summary>
        /// 样品状态， 关联 SampleStatus
        /// </summary>
        public string Status { get; set; }

        /// <summary>
        /// 样品完成时间
        /// </summary>
        public DateTime? CompleteTime { get; set; }

        /// <summary>
        /// 该样品需要自动跳过的流程步骤
        /// </summary>
        public string SkipSequence { get; set; }

        /// <summary>
        /// 样品关联的报告名
        /// </summary>
        public string ReportName { get; set; }

        /// <summary>
        /// 是否留样 如果勾选留样，在样品在完成检测后，自动启动留样处理流程，并在留样表中留有相应记录。
        /// </summary>
        public bool IsRetention { get; set; }

        /// <summary>
        /// 出报告时是否起作用
        /// </summary>
        public bool IsRelease { get; set; }

        /// <summary>
        /// 留样配置ID
        /// </summary>
        public string RetentionConfigId { get; set; }

        public Sample GetInstance(string Id)
        {
            var dbContext = new CoreLimsContext();
            return dbContext.Sample.Where(s => s.Id == Id).FirstOrDefault();
        }
    }

    /// <summary>
    /// 关联批次样品的样品单（也叫委托单、采样单、送样单等）
    /// </summary>
    public partial class SampleSampleBatch
    {
        public SampleSampleBatch()
        {
            this.Id = SAMPLE._newId();
            this.CreatTime = DateTime.Now;
        }

        /// <summary>
        /// 委托单ID,唯一标识
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// 委托单号，用户自定义的委托单号，关联样品中的 BatchId
        /// </summary>
        public string BatchId { get; set; }

        /// <summary>
        /// 扩展字段1
        /// </summary>
        public string Ex1 { get; set; }

        public string Ex2 { get; set; }

        public string Ex3 { get; set; }

        /// <summary>
        /// 送样部门或单位
        /// </summary>
        public string SendDepartment { get; set; }
        
        /// <summary>
        /// 送样人
        /// </summary>
        public string SendPerson { get; set; }

        /// <summary>
        /// 送样时间
        /// </summary>
        public DateTime? SendTime { get; set; }

        /// <summary>
        /// 登录人ID
        /// </summary>
        public string PersonId { get; set; }

        /// <summary>
        /// 登录人姓名
        /// </summary>
        public string PersonName { get; set; }

        /// <summary>
        /// 委托单登记时间
        /// </summary>
        public DateTime CreatTime { get; set; }
    }

    /// <summary>
    /// 登录样品关联关系映射表
    /// </summary>
    public partial class SampleLoginRelation
    {
        public string Id { get; set; }

        /// <summary>
        /// 登录样品ID
        /// </summary>
        public string SampleId { get; set; }

        /// <summary>
        /// 登录样品关联的测试ID
        /// </summary>
        public string TestId { get; set; }

        /// <summary>
        /// 登录样品关联的分析项ID，独立添加和测试包含的分析项都在这里
        /// </summary>
        public string AnalyteId { get; set; }

        /// <summary>
        /// 分析项的检测次数，该值是从测试关联的分析项中带过来的 或者 是从样品定义中直接关联过来。
        /// 如果该项是测试，则这个值是测试的重复次数。
        /// </summary>
        public int DetectionTimes { get; set; }

        /// <summary>
        /// 如果 TestId 不为空，是测试关联的指标集。如果 TestId 为空，则是测试关联的指标集。
        /// </summary>
        public string SpecCollectionId { get; set; }

        /// <summary>
        /// 测试关联的方法
        /// </summary>
        public string MethodId { get; set; }

        /// <summary>
        /// 指示当前的记录是否为默认的 指标集 或 方法
        /// </summary>
        public bool? IsDefault { get; set; }
    }

    /// <summary>
    /// 样品定义
    /// </summary>
    public partial class SampleSampleDefinition
    {
        public SampleSampleDefinition()
        {
            Id = SAMPLE._newId();
            IsRelease = true;
            IsRetention = false;
        }

        public string Id { get; set; }

        /// <summary>
        /// 样品名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 样品描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 样品类型 临时样/常规样/批次样/环境样/稳定性
        /// </summary>
        public string Classification { get; set; }

        /// <summary>
        /// 样品分类：原材料、中控样、半成品、成品等
        /// </summary>
        public string GenricClass { get; set; }

        /// <summary>
        /// 所属实验室
        /// </summary>
        public string Site { get; set; }

        /// <summary>
        /// 所属工作组
        /// </summary>
        public string Group { get; set; }

        /// <summary>
        /// 采样点
        /// </summary>
        public string SamplingPoint { get; set; }

        /// <summary>
        /// (暂)物料ID 如果该样品是QC样，此处指定和库存关联的物料，可以实现动态库存
        /// </summary>
        public string MaterialId { get; set; }

        /// <summary>
        /// 该样品需要自动跳过的流程步骤
        /// </summary>
        public string SkipSequence { get; set; }

        /// <summary>
        /// 默认关联的流程ID
        /// </summary>
        public string WorkFlowId { get; set; }

        /// <summary>
        /// 默认关联的流程名
        /// </summary>
        public string WorkFlowName { get; set; }

        /// <summary>
        /// 样品关联的报告名
        /// </summary>
        public string ReportName { get; set; }

        /// <summary>
        /// 是否发布 样品在COA报告中是否发布
        /// </summary>
        public bool IsRelease { get; set; }

        /// <summary>
        /// 是否留样 如果勾选留样，在样品在完成检测后，自动启动留样处理流程，并在库存中留有相应记录。
        /// </summary>
        public bool IsRetention { get; set; }

        /// <summary>
        /// 默认样品编号，该字段在登录时将复制到样品的自定义编号字段。
        /// 对于标样或QC样，提供默认编号，方便后续的查询统计。
        /// </summary>
        public string DefaultNumber { get; set; }

        /// <summary>
        /// 留样配置ID
        /// </summary>
        public string RetentionConfigId { get; set; }

        public RetentionConfig RetentionConfig(CoreLimsContext dbContext) => 
            dbContext.RetentionConfig.Where(s => s.Id == this.RetentionConfigId).FirstOrDefault();
    }

    /// <summary>
    /// 指标 和 指标集
    /// </summary>
    public partial class SampleSpec
    {
        public string Id { get; set; }

        /// <summary>
        /// 指标代码，可以对应分析项的代码
        /// </summary>
        public string Code { get; set; }

        /// <summary>
        /// 指标名称，可以对应分析项的名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 一级分类，可以对应分析项的分类
        /// </summary>
        public string FirstGroup { get; set; }

        /// <summary>
        /// 二级分类
        /// </summary>
        public string SecondGroup { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 三倍低限
        /// </summary>
        public string LowA { get; set; }

        /// <summary>
        /// 二倍低限
        /// </summary>
        public string LowB { get; set; }

        /// <summary>
        /// 标准值
        /// </summary>
        public string StandardValue { get; set; }

        /// <summary>
        /// 二倍高限
        /// </summary>
        public string HighB { get; set; }

        /// <summary>
        /// 三倍高限
        /// </summary>
        public string HighA { get; set; }

        /// <summary>
        /// 验收标准，出报告时放在报告上描述合格范围的文本信息
        /// </summary>
        public string AcceptanceCriteria { get; set; }

        /// <summary>
        /// 自定义计算规则
        /// </summary>
        public string AcceptanceRules { get; set; }

        /// <summary>
        /// 版本
        /// </summary>
        public int Version { get; set; }

        /// <summary>
        /// 发布状态
        /// </summary>
        public string ReleaseStatus { get; set; }

        /// <summary>
        /// 是否启用
        /// </summary>
        public bool Enable { get; set; }

        /// <summary>
        /// 是否为指标集的标志
        /// </summary>
        public bool IsCollection { get; set; }

        /// <summary>
        /// 指标集ID,这个ID就是定义指标集的指标ID
        /// 如果该字段为空，则该记录为指标集定义。如果填写了ID，则为指标集包含的指标定义
        /// </summary>
        public string CollectionId { get; set; }

        /// <summary>
        /// 指标集包含的分析项ID
        /// </summary>
        public string AnalyteId { get; set; }

    }

    /// <summary>
    /// 测试包含的关系映射表
    /// </summary>
    public partial class SampleTestRelation
    {
        public string Id { get; set; }

        /// <summary>
        /// 测试定义ID
        /// </summary>
        public string TestDefinitionId { get; set; }

        /// <summary>
        /// 分析项ID
        /// </summary>
        public string AnalytesId { get; set; }

        /// <summary>
        /// 分析项检测次数
        /// </summary>
        public int DetectionTimes { get; set; }

        /// <summary>
        /// 指标集ID
        /// </summary>
        public string SpecCollectionId  { get; set; }

        /// <summary>
        /// 方法ID
        /// </summary>
        public string MethodId  { get; set; }

        /// <summary>
        /// 针对同一个测试里的分析项进行的相关计算
        /// </summary>
        public string CalculationRules { get; set; }

        /// <summary>
        /// 该值指示方法或指标集是否为默认
        /// </summary>
        public bool? IsDefault { get; set; }
    }

    /// <summary>
    /// 测试定义
    /// </summary>
    public partial class SampleTestDefinition
    {
        public string Id { get; set; }

        /// <summary>
        /// 测试名称
        /// </summary>
        public string TestName { get; set; }

        /// <summary>
        /// 一级分类
        /// </summary>
        public string FirstGroup { get; set; }

        /// <summary>
        /// 二级分类
        /// </summary>
        public string SecondGroup { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 版本
        /// </summary>
        public int? Version { get; set; }

        /// <summary>
        /// 发布状态 暂未用
        /// </summary>
        public string ReleaseStatus { get; set; }
    }

    /// <summary>
    /// 样品组定义
    /// </summary>
    public partial class SampleSampleGroup
    {
        public SampleSampleGroup()
        {
            Id = SAMPLE._newId();
            SampleNumber = 1;
        }

        public string Id { get; set; }

        /// <summary>
        /// 样品组ID，如果该字段为空，则说明是组定义
        /// </summary>
        public string SampleGroupId { get; set; }

        /// <summary>
        /// 样品组类型
        /// </summary>
        public string Type { get; set; }

        /// <summary>
        /// 样品组名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 样品组描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 所属实验室
        /// </summary>
        public string Site { get; set; }

        /// <summary>
        /// 所属工作组
        /// </summary>
        public string Group { get; set; }

        /// <summary>
        /// 组中所包含的样品ID
        /// </summary>
        public string SampleId { get; set; }

        /// <summary>
        /// 样品个数
        /// </summary>
        public int SampleNumber { get; set; }

        public SampleGroup Copy(SampleGroup other)
        {
            this.Name = other.Name;
            this.Type = other.Type;
            this.Site = other.Site;
            this.Group = other.Group;
            this.Description = other.Description;
            return this;
        }
    }

    /// <summary>
    /// 方法管理
    /// </summary>
    public partial class SampleMethod
    {
        public string Id { get; set; }

        /// <summary>
        /// 方法编码
        /// </summary>
        public string Code { get; set; }

        /// <summary>
        /// 方法名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 方法类型  国标/行标/企标
        /// </summary>
        public string Type { get; set; }

        /// <summary>
        /// 方法描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 生效日期
        /// </summary>
        public DateTime? EffectiveDate { get; set; }

        /// <summary>
        /// 有效期至
        /// </summary>
        public DateTime? ExpireDate { get; set; }

        /// <summary>
        /// 标准操作程序关联的记录单
        /// </summary>
        public string RecordSheet { get; set; }

        /// <summary>
        /// 方法版本号
        /// </summary>
        public string Version { get; set; }

        /// <summary>
        /// 审批状态
        /// </summary>
        public string Status { get; set; }

        /// <summary>
        /// 是否启用
        /// </summary>
        public bool Enable { get; set; }
    }

    /// <summary>
    /// 留样管理
    /// </summary>
    public partial class RetentionSample : IWorkFlow<RetentionSample>
    {
        /// <summary>
        /// 这个ID就是Sample的ID
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// 材料代码, 未使用
        /// </summary>
        public string MaterialCode { get; set; }

        /// <summary>
        /// 样品名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 样品ID,根据定义规则由系统自动生成的ID，由于存在重测的样品，所以该字段是允许重复的。
        /// </summary>
        public string SampleId { get; set; }

        /// <summary>
        /// 样品编号,客户附加到登录样品上的编号，也可以理解为内部编号或自定义编号，可为空
        /// </summary>
        public string SampleNumber { get; set; }

        /// <summary>
        /// 批次号，标识一个批次样品的编号，也可以理解为委托单号等。
        /// </summary>
        public string BatchId { get; set; }

        /// <summary>
        /// 样品类型 临时样/常规样/批次样/环境样/稳定性
        /// </summary>
        public string Classification { get; set; }

        /// <summary>
        /// 样品分类：原材料、中控样、半成品、成品等
        /// </summary>
        public string GenricClass { get; set; }

        /// <summary>
        /// 样品所属实验室
        /// </summary>
        public string Site { get; set; }

        /// <summary>
        /// 样品所属工作组
        /// </summary>
        public string Group { get; set; }

        /// <summary>
        /// 存储留样使用的容器或包装
        /// </summary>
        public string Container { get; set; }

        /// <summary>
        /// 留样总量
        /// </summary>
        public decimal? Quantity { get; set; }

        /// <summary>
        /// 数量单位
        /// </summary>
        public string Unit { get; set; }

        /// <summary>
        /// 容器(包装)数量
        /// </summary>
        public int? ContainerNumber { get; set; }

        /// <summary>
        /// 注册时间 留样被记录到该表的时间。此时，留样等待接收
        /// </summary>
        public DateTime? RegistrationTime { get; set; }

        /// <summary>
        /// 留样接收人ID
        /// </summary>
        public string RecipientId { get; set; }

        /// <summary>
        /// 留样接收人姓名
        /// </summary>
        public string RecipientName { get; set; }

        /// <summary>
        /// 留样接收时间
        /// </summary>
        public DateTime? ReceptionTime { get; set; }

        /// <summary>
        /// 存储位置
        /// </summary>
        public string Position { get; set; }

        /// <summary>
        /// 存储条件
        /// </summary>
        public string StorageConditionsId { get; set; }

        /// <summary>
        /// 到期时间 该值通过登录时间和留样时长计算得到
        /// </summary>
        public DateTime? KeepTo { get; set; }

        /// <summary>
        /// 到期提醒天数
        /// </summary>
        public int? Remind { get; set; }

        /// <summary>
        /// 留样处置人ID
        /// </summary>
        public string DisposerId { get; set; }

        /// <summary>
        /// 留样处置人姓名
        /// </summary>
        public string DisposerName { get; set; }

        /// <summary>
        /// 留样处置时间
        /// </summary>
        public DateTime? DisposerTime { get; set; }

        /// <summary>
        /// 接收备注
        /// </summary>
        public string Note { get; set; }

        /// <summary>
        /// 留样处置说明
        /// </summary>
        public string DisposalInstructions { get; set; }

        /// <summary>
        /// 领用时是否审批
        /// </summary>
        public bool UseApproval { get; set; }

        /// <summary>
        /// 处置时是否需要审批
        /// </summary>
        public bool DisApproval { get; set; }

        public RetentionSample GetInstance(string Id)
        {
            var dbContext = new CoreLimsContext();
            return dbContext.RetentionSample.Where(s => s.Id == Id).FirstOrDefault();
        }

    }

    /// <summary>
    /// 留样配置管理
    /// </summary>
    public partial class RetentionConfig
    {
        public RetentionConfig()
        {
            this.Id = Guid.NewGuid().ToString();
        }
        public string Id { get; set; }

        /// <summary>
        /// 配置名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 存储位置
        /// </summary>
        public string Position { get; set; }

        /// <summary>
        /// 存储条件
        /// </summary>
        public string StorageConditions { get; set; }

        /// <summary>
        /// 存储留样使用的容器或包装
        /// </summary>
        public string Container { get; set; }

        /// <summary>
        /// 每个容器(包装)中的样品数量
        /// </summary>
        public decimal? Quantity { get; set; }

        /// <summary>
        /// 数量单位
        /// </summary>
        public string Unit { get; set; }

        /// <summary>
        /// 容器(包装)数量
        /// </summary>
        public int? ContainerNumber { get; set; }

        /// <summary>
        /// 样品留存时长
        /// </summary>
        public int? Duration { get; set; }

        /// <summary>
        /// 留样时指定留存时间长度的单位
        /// </summary>
        public string DurationUnit { get; set; }

        /// <summary>
        /// 到期提前提醒天数
        /// </summary>
        public int? Remind { get; set; }

        /// <summary>
        /// 领用时是否审批
        /// </summary>
        public bool UseApproval { get; set; }

        /// <summary>
        /// 处置时是否需要审批
        /// </summary>
        public bool DisApproval { get; set; }

        /// <summary>
        /// 返回到期时间。如果样品定义中设置了留样，则该值为：样品登录时间 + 样品定义中的留样时间
        /// </summary>
        /// <param name="reconfig"></param>
        /// <returns></returns>
        public DateTime? KeepTo()
        {
            if (this.Duration == null || this.DurationUnit == null)
                return null;

            if (this.DurationUnit == "日")
                return DateTime.Now.AddDays((int)this.Duration);
            if (this.DurationUnit == "月")
                return DateTime.Now.AddMonths((int)this.Duration);
            if (this.DurationUnit == "年")
                return DateTime.Now.AddYears((int)this.Duration);
            else
                return null;
        }
    }

    /// <summary>
    /// 留样领用记录
    /// </summary>
    public partial class RetentionUse : IWorkFlow<RetentionUse>
    {
        public RetentionUse()
        {
            this.Id = Guid.NewGuid().ToString();
            this.UseDateTime = DateTime.Now;
        }

        public string Id { get; set; }

        /// <summary>
        /// 对应的留样ID
        /// </summary>
        public string RetentionSampleId { get; set; }

        /// <summary>
        /// 对应系统自动生成的样品编号
        /// </summary>
        public string SampleId { get; set; }

        /// <summary>
        /// 领用包装数量，对于有些留样不是整包领而是取其中一部分，这时包装数量为0
        /// </summary>
        public int ContainerNumber { get; set; }

        /// <summary>
        /// 领用总量
        /// </summary>
        public decimal Quantity { get; set; }

        /// <summary>
        /// 数量单位
        /// </summary>
        public string Unit { get; set; }

        /// <summary>
        /// 领用人ID
        /// </summary>
        public string UserId { get; set; }

        /// <summary>
        /// 领用人姓名
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 领用时间
        /// </summary>
        public DateTime UseDateTime { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        public string Note { get; set; }

        public RetentionUse GetInstance(string Id)
        {
            var dbContext = new CoreLimsContext();
            return dbContext.RetentionUse.Where(s => s.Id == Id).FirstOrDefault();
        }

    }

    /// <summary>
    /// 该类用来指示流程中那些步骤需要自动跳过
    /// </summary>
    public class SkipSequence
    {
        /// <summary>
        /// 该值如果为 ture ，说明该步骤自动跳过
        /// </summary>
        public bool Skip { get; set; }

        /// <summary>
        /// 需要自动跳过的步骤ID
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// 流程步骤名称
        /// </summary>
        public string StepName { get; set; }
    }
}
